//
// Copyright (c) 2014, 保留所有权利。
//
// BookingSync.java
//
// 作    者：王红燕
// 当前版本：1.0
// 2014 下午1:15:28
//
// 
//
package com.vanke.agent.sync;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;

import org.apache.log4j.Logger;

import com.vanke.agent.ADataSource;
import com.vanke.agent.C;
import com.vanke.agent.Cfg;
import com.vanke.agent.bean.FollowRecord;
import com.vanke.agent.common.CstUtil;
import com.vanke.agent.common.RecommendUtil;
import com.vanke.agent.common.TradeUtil;
import com.vanke.agent.common.Util;
import com.vanke.agent.common.log.LoggerUtil;

/**
 *
 */
public class BookingSync extends AgentSync {
	Logger log = LoggerUtil.getLoggerByName("booking_sync");

	@Override
	public void sync() {
		long now = System.currentTimeMillis();
		int added = 0, updated = 0;
		int record = 0;

		String timeStr = dateFormat.format(Util.offMinute(bookingCfg.beginTime,
				rebackOffset));
		Timestamp t = new Timestamp(System.currentTimeMillis());
		//		bookingCfg.beginTime = new Date(System.currentTimeMillis());

		log.info("SYNC[02]sync booking");
		String table = "s_Booking";
		String fields = C.FIELDS_BOOKING;

		Connection con = ADataSource.getConnection(ADataSource.SCHEMA_MY);
		Connection wcon = ADataSource.getConnection(ADataSource.SCHEMA_BIZ);

		try {
			String querySql = "SELECT " + fields + "  FROM " + table;
			querySql += " where CreatedOn>=? AND CreatedOn<? order by CreatedOn asc";
			log.info("SYNC_SQL[02]" + querySql + "[" + timeStr + "~"
					+ dateFormat.format(t) + "]");

			String insertSql = CstUtil.formatInsertSql(table, fields);
			PreparedStatement wpstmt = wcon.prepareStatement(insertSql);
			int columns = fields.split(",").length;

			// 更新
			String updateSql = CstUtil.formatUpdateSql(table, fields);
			updateSql += " where BookingGUID=?";
			PreparedStatement updatePstmt = wcon.prepareStatement(updateSql);

			PreparedStatement pstmt = con.prepareStatement(querySql,
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_READ_ONLY);
			pstmt.setString(1, timeStr);
			pstmt.setTimestamp(2, t);

			ResultSet rs = pstmt.executeQuery();
			while (rs.next()) {
				record++;
				bookingCfg.beginTime = new Date(rs.getTimestamp("CreatedOn")
						.getTime());

				String BookingGUID = rs.getString("BookingGUID");
				boolean exists = exists(wcon, BookingGUID);
				try {
					if (exists) {
						log.info("SYNC_IGNORE[02]已处理的认筹，忽略不处理[" + BookingGUID
								+ "]");
						for (int i = 1; i <= columns; i++) {
							updatePstmt.setString(i, rs.getString(i));
						}
						updatePstmt.setString(columns + 1, BookingGUID);
						updatePstmt.executeUpdate();
						updated++;
						continue;
					} // end if (exists) 
					// 保存映射与跟进，并通知
					// 同步分表，并产生通知；为了懒省事，把创建时间和金额直接传过去
					boolean hasRefCst = syncBooking2Cst(rs.getString("BookingGUID"),
							rs.getString("ProjGUID"), rs.getTimestamp("CreatedOn"),
							rs.getDouble("Total"), exists);
					if (!hasRefCst) {
						log.info("SYNC_SAVE[02]认筹客户在数据中心未找到[" + BookingGUID + "]");
						continue;
					}
					log.info("SYNC_SAVE[02]保存认筹记录[" + BookingGUID + "]");
					for (int i = 1; i <= columns; i++) {
						wpstmt.setString(i, rs.getString(i));
					}
					wpstmt.executeUpdate();
					added++;
				} catch (Exception e) {
					log.error("SYNC_ERR[02]保存认筹异常：" + e);
				}
			} // end while

			// 保存配置，最后一次的时间
			Cfg.set(bookingCfg.cfgKey,
					dateFormat.format(bookingCfg.beginTime));
			Cfg.save();

			// 关闭
			ADataSource.close(rs);
			ADataSource.close(pstmt);
			ADataSource.close(wpstmt);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("SYNC_ERR[02]同步出错: " + e);
		} finally {
			ADataSource.close(con);
			ADataSource.close(wcon);
		}
		now = System.currentTimeMillis() - now;
		log.info("SYNC[02]" + added + " booking added and " + updated
				+ " updated, by " + record + " records. spend " + now + " ms");
		log.info("SYNC_END[02]");
	} // ~sync

	// 保存认筹客户，返回是否在数据中心关联上客户
	boolean syncBooking2Cst(String bookingGUID, String projGUID, Timestamp time,
			double total,boolean exists) {
		Connection myCon = ADataSource.getConnection(ADataSource.SCHEMA_MY);
		PreparedStatement myPstmt = null;
		ResultSet rs = null;

		Connection bizCon = null;
		PreparedStatement bizPstmt = null;

		String fields = C.FIELDS_BOOKING2CST;
		try {
			String sql = "select " + fields
					+ " from s_Booking2Cst  where BookingGUID=?";
			myPstmt = myCon.prepareStatement(sql,
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_READ_ONLY);
			myPstmt.setString(1, bookingGUID);
			rs = myPstmt.executeQuery();
			// 如果没查到，记录日志，结束
			if (!rs.next()) {
				log.info("SYNC_IGNORE[02]未找到关联客户[" + bookingGUID + "]");
				return false;
			}

			bizCon = ADataSource.getConnection(ADataSource.SCHEMA_BIZ);
			String insertSql = CstUtil.formatInsertSql("s_Booking2Cst", fields);
			bizPstmt = bizCon.prepareStatement(insertSql);
			int columns = fields.split(",").length;
			boolean hasOne = false;
			do {
				// 根据明源GUID找应用中心ＧＵＩＤ，
				String oriCstGUID = rs.getString("CstGUID");
				long uid = CstUtil.getCstGUIDByOriGuid(bizCon, oriCstGUID);
				if (uid == 0) {
					// 查不到，则到明源查义主档记录的身份证或手机，再反查数据中心
					log.info("booking no CstGUID found for:" + oriCstGUID
							+ ", retrieve again");
					uid = CstUtil.retrieveMemship(oriCstGUID);
				}
				// 更新售前客户状态
				// 仍未找到，则表示匹配不上该客户，即被彻底洗掉了，且现存主档也不规范
				if (uid == 0) {
					log.warn("SYNC_WARN[02]关联客户在数据中心未找到[" + oriCstGUID + "]");
					continue;
				}
				// 取项目Code
				String projCode = getProjectCode(myCon, projGUID);

				String comment = "认筹";
				if (hasOne) { // 因为是同一笔交易查出来的，因此只其中一个算金额
					comment = "联名认筹";
				}
				// 无论是否需要通知或是否匹配到客户，先保存跟进记录
				FollowRecord fr = new FollowRecord();
				fr.setCstGUID(uid);
				fr.setOriCstGUID(oriCstGUID);
				fr.setProjGUID(projGUID);
				fr.setProjCode(projCode);
				fr.setReceiveType("认筹");
				fr.setFollowType( C.FOLLOW_BOOKING);
				fr.setCstType(4);
				fr.setReceiveDate(time);
				fr.setTotal(total);
				fr.setTradeGUID(bookingGUID);
				fr.setComment(comment);
				fr.setRoomGUID("");
				fr.setRoom("");
				fr.setHuxing("");
				fr.setRefGUID(bookingGUID);
				TradeUtil.saveFollowRecord(bizCon, fr, log);

				try {
					for (int i = 1; i <= columns; i++) {
						bizPstmt.setString(i, rs.getString(i));
					}
					bizPstmt.executeUpdate();
				} catch (Exception e) {
				}
				//====== 更新客户状态开始==========
				//String[]：RecommendGUID,cstStatus,tradeGUID,amount,tradeStatusTrack,tradeStatus
				String[] recommend=RecommendUtil.getAgentCstRecommed(bizCon,uid,projCode);
				if(recommend!=null){
					if(!exists){
						RecommendUtil.updateCstStatusForTrade(bizCon,uid,recommend[0],
								recommend[2],Float.valueOf(recommend[3]),recommend[4],
								C.FOLLOW_BOOKING,time,
								bookingGUID,total,0f,
								"认筹",C.TRADE_STATUS_NEW);
					}
				}else{
					log.warn("SYNC_WARN[02]关联客户推荐记录未找到[cstGUID=" + uid+",projCode="+projCode + "]");
				}
				//====== 更新客户状态接结束==========
				// 如果保存了其中一个客户，则金额置0
				hasOne = true;
				TradeUtil.sendNotice(//
						C.NOTICE_BOOKING, 	// 消息类型
						uid,				// 客户GUID 
						projCode, 			// 项目编号
						time, 				// 时间
						total, 				// 金额
						C.FOLLOW_BOOKING,	// 跟进类型
						comment, 			// 备注说明
						C.TRADE_STATUS_NONE,//
						null, null, null);
			} while (rs.next());// end while (rs.next())
			return hasOne;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return false;
		} finally {
			ADataSource.close(rs, myPstmt, myCon);
			ADataSource.close(null, bizPstmt, bizCon);
		}
	} //~

	boolean exists(Connection con, String BookingGUID) {
		String sql = "select BookingGUID from s_Booking where BookingGUID=?";
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			pstmt = con.prepareStatement(sql);
			pstmt.setString(1, BookingGUID);
			rs = pstmt.executeQuery();
			return rs.next();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			ADataSource.close(rs, pstmt, null);
		}
		return false;
	}
} ///~
